package com.one.blocks.rbac.exception;

import com.one.blocks.mvc.exception.BusinessException;
import com.one.blocks.mvc.response.ResponseHelper;
import com.one.blocks.mvc.response.WebResponse;
import com.one.blocks.rbac.enums.RbacResponseEnum;
import com.one.blocks.security.exception.AuthcException;
import com.one.blocks.security.exception.AuthzException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ValidationException;

/**
 * @author linfuxin Created on 2022-02-14 16:22:21
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 未捕获异常
     *
     * @param e Exception
     * @return 统一格式异常响应
     */
    @ExceptionHandler(Exception.class)
    public WebResponse<Void> unknown(Exception e) {
        log.error("未知异常!", e);
        return ResponseHelper.fail(RbacResponseEnum.UNKNOWN_ERROR);
    }

    /**
     * 系统业务异常
     *
     * @param e Exception
     * @return 统一格式异常响应
     */
    @ExceptionHandler(BusinessException.class)
    public WebResponse<Void> bizException(BusinessException e) {
        log.warn("业务异常!code={},reason={}", e.getCode(), e.getMsg());
        return ResponseHelper.fail(e.getCode(), e.getMsg());
    }

    /**
     * 系统业务异常
     *
     * @param e Exception
     * @return 统一格式异常响应
     */
    @ExceptionHandler({AuthcException.class})
    public WebResponse<Void> authException(AuthcException e) {
        return ResponseHelper.fail(e.getCode(), e.getMsg());
    }


    /**
     * 系统业务异常
     *
     * @param e Exception
     * @return 统一格式异常响应
     */
    @ExceptionHandler({AuthzException.class})
    public WebResponse<Void> authException(AuthzException e) {
        return ResponseHelper.fail(e.getCode(), e.getMsg());
    }

    /**
     * 与@Validated相关,controller非bean参数校验异常
     *
     * @param e ValidationException
     * @return 统一格式异常响应
     */
    @ExceptionHandler({ValidationException.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public WebResponse<Void> handValidationException(ValidationException e) {
        return ResponseHelper.fail(RbacResponseEnum.BAD_REQUEST.getCode(), e.getMessage());
    }

    /**
     * 与@Validated相关,controllerbean参数校验异常
     *
     * @param e ValidationException
     * @return 统一格式异常响应
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public WebResponse<Void> handMethodValidationException(MethodArgumentNotValidException e) {
        return ResponseHelper.fail(RbacResponseEnum.BAD_REQUEST.getCode(), resolveErrorMessage(e.getBindingResult().getAllErrors().get(0)));
    }


    //    @Override
//    protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
//        ObjectError objectError = ex.getBindingResult().getAllErrors().get(0);
//        StringBuilder errorMessage = resolveErrorMessage(objectError);
//        return handleExceptionInternal(ex, errorMessage, headers, status, request);
//    }
//
//    @Override
//    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
//        if (log.isDebugEnabled()) {
//            log.debug("Spring MVC Exception!", ex);
//        }
//        String errMsg;
//        // todo AbstractHandlerExceptionResolver 去除警告日志
//        if (ex instanceof MethodArgumentNotValidException) {
//            ObjectError objectError = ((MethodArgumentNotValidException) ex).getBindingResult().getAllErrors().get(0);
//            errMsg = resolveErrorMessage(objectError).toString();
//        } else {
//            errMsg = ex.getMessage();
//        }
//        return new ResponseEntity<>(body == null ? errMsg : body.toString(), headers, status);
//    }
//
//    @Override
//    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
//        ObjectError objectError = ex.getBindingResult().getAllErrors().get(0);
//        StringBuilder errorMessage = resolveErrorMessage(objectError);
//        return handleExceptionInternal(ex, errorMessage, headers, status, request);
//    }
//
    private String resolveErrorMessage(ObjectError objectError) {
        return objectError instanceof FieldError ?
                ((FieldError) objectError).getField() + objectError.getDefaultMessage() : objectError.getDefaultMessage();
    }
}
